package com.mpj.yolov12

import android.app.Activity
import android.content.Context
import android.content.res.AssetManager
import android.graphics.BitmapFactory
import android.graphics.PixelFormat
import android.util.Log
import android.view.Surface
import androidx.core.graphics.scale
import java.io.ByteArrayOutputStream
import java.net.InetAddress

class DataStreamProcessHelper private constructor() : OnPacketReceivedListener {

    companion object {
        val instance: DataStreamProcessHelper by lazy { DataStreamProcessHelper() }
    }

    private val TAG = DataStreamProcessHelper::class.java.simpleName

    // 标记是否已经推送过广播
    private var pushed: Boolean = false

    // YOLOV12处理类
    private var yolov12: Yolov12 = Yolov12()

    // UDP广播监听器
    private lateinit var udpListener: UdpBroadcastListener

    // 与UI交互的关键节点回调
    private lateinit var onUIProcessListener: OnUIProcessListener

    // UDP广播的信息，需要连接的IP地址和端口号
    private var udpInfo: UDPInfo? = null

    // UDP接收器 - 监听图片数据的传输
    private var udpReceiver: UdpReceiver? = null

    // 用于存储每个帧的数据包
    private var frames = mutableMapOf<Int, MutableMap<Int, ByteArray>>()

    // 当前处理的帧序号
    private var currentFrameSeq = -1

    // 当前帧的包总数
    private var currentFramePkgCount = 0

    // 已经接收到的包数量
    private var receivedPacketCount = 0

    // 用于显示图像的Surface
    private lateinit var mSurface: Surface
    private lateinit var assets: AssetManager

    private lateinit var imageView: BitmapSurfaceView

    /**
     * 设置显示图像的Surface
     */
    fun init(context: Activity) {
        // 初始化AssetManager
        this.assets = context.assets
        // 初始化图像显示控件
        this.imageView = BitmapSurfaceView(context)
        // 请求权限
        requestPermission(context)
        // 打开WiFi
        openWifiManager(context)
        // 初始化ncnn模型
        loadModel()
        // 创建UDP广播监听器
        createUdpBroadcastListener()
    }

    fun requestPermission(context: Activity) {
        PermissionHelper.requestPermission(context)
    }

    fun initImage(context: Context) {
        this.mSurface = imageView.holder.surface
        this.imageView.holder.setFormat(PixelFormat.RGBA_8888)
        // 重置宽高 640*480
        var params = imageView.layoutParams
        params.width = (640 * 1.5).toInt()
        params.height = (480 * 1.5).toInt()
        imageView.layoutParams = params
    }

    fun getImageView(): BitmapSurfaceView {
        return imageView
    }

    private fun loadModel() {
        var loadSuccess = yolov12.loadModel(assets, 0, 0);
        Log.e(TAG, "loadModel is success $loadSuccess")
    }

    fun setUIProcessListener(onUIProcessListener: OnUIProcessListener) {
        this.onUIProcessListener = onUIProcessListener
    }

    /**
     * 创建UDP监听器
     */
    fun createUdpBroadcastListener() {
        udpListener = UdpBroadcastListener(52110)
        // 设置消息回调
        udpListener.onMessageReceived = { message, senderIp, senderPort ->
            Log.d("udp-info", "ip:$senderIp, port:$senderPort")
            udpInfo = UDPInfo(senderIp, senderPort)
            if (!pushed) {
                // 停止监听UDP广播
                stopUdpBroadcastListening()
                // 启动UDP接收器
                startUdpReceiver()
                // 更新UI
                onUIProcessListener.onUDPInfoReceived(udpInfo!!)
                pushed = true
            }
        }
    }

    /**
     * 开始监听UDP广播
     */
    fun startUdpBroadcastListening() {
        udpListener.startListening()
        onUIProcessListener.updateReceivedDataStatus("开始监听UDP广播", true)
    }

    /**
     * 停止监听UDP广播
     */
    fun stopUdpBroadcastListening() {
        stopUdpReceiver()
        pushed = false
        udpListener.stopListening()
        onUIProcessListener.updateReceivedDataStatus("停止监听UDP广播", false)
    }


    /**
     * 启动UDP接收器
     */
    fun startUdpReceiver() {
        if (udpInfo == null){
            return
        }
        try {
            udpReceiver = UdpReceiver(this, udpInfo!!.senderPort)
            startVideoStream(udpInfo!!.senderIp, udpInfo!!.senderPort)
        } catch (e: Exception) {
            Log.e(TAG, "启动UDP接收器失败", e)
            onUIProcessListener.updateReceivedDataStatus("启动UDP接收器失败: ${e.message}", false)
        }
    }

    /**
     * 停止UDP接收器
     */
    fun stopUdpReceiver() {
        udpReceiver?.stop()
        udpReceiver = null
    }

    /**
     * 开始视频流
     */
    private fun startVideoStream(ip: String, port: Int) {
        udpReceiver?.sendCommandPacket(ip, port, null)
    }

    /**
     * 处理数据包
     */
    override fun onPacketReceived(data: ByteArray, address: InetAddress, port: Int) {
        if (data.size < 4) {
            Log.e(TAG, "收到无效数据包: 长度小于4字节")
            return
        }

        // 解析包头
        val frameSeq = data[0].toInt() and 0xFF  // 帧序号 0-255
        val eofFlag = data[1].toInt() and 0xFF   // EOF标志 0或1
        val pkgCount = data[2].toInt() and 0xFF  // 包总数
        // data[3] 预留字节

        Log.d(TAG, "收到数据包: 帧=$frameSeq, EOF=$eofFlag, 包数=$pkgCount, 长度=${data.size}")

        // 如果是新帧，重置状态
        if (frameSeq != currentFrameSeq) {
            resetFrameState(frameSeq, pkgCount)
        }

        // 提取数据部分(跳过4字节包头)
        val payload = data.copyOfRange(4, data.size)

        // 将数据包存储到当前帧
        val packetIndex = receivedPacketCount
        if (!frames.containsKey(frameSeq)) {
            frames[frameSeq] = mutableMapOf()
        }
        frames[frameSeq]?.put(packetIndex, payload)
        receivedPacketCount++
        currentFramePkgCount = frames[frameSeq]!!.keys.count()
        onUIProcessListener.updateReceivedDataStatus(
            "帧 $frameSeq: 已接收 $receivedPacketCount/$pkgCount 包",
            true
        )

        // 当EOF为0且接收到的包数等于包总数时，组装图像
        if (eofFlag == 1 && receivedPacketCount == pkgCount) {
            try {
                processCompleteFrame(frameSeq)
            } catch (e: Exception) {
                resetFrameState(frameSeq, pkgCount)
            }
        }
    }

    /**
     * 每一帧图片数据处理
     */
    private fun processCompleteFrame(frameSeq: Int) {
        try {
            val packets = frames[frameSeq]

            if (packets != null && packets.size == currentFramePkgCount) {
                // 合并所有数据包
                val outputStream = ByteArrayOutputStream()

                for (i in 0 until currentFramePkgCount) {
                    val packet = packets[i]
                    if (packet != null) {
                        outputStream.write(packet)
                    } else {
                        throw RuntimeException("缺少包 $i")
                    }
                }

                val imageData = outputStream.toByteArray()
                val bitmap = BitmapFactory.decodeByteArray(imageData, 0, imageData.size)

                if (bitmap != null) {
                    Log.d(TAG, "成功创建图像，大小: ${bitmap.width}x${bitmap.height}")
                    // 1 将图片进行向左旋转90度 适配菌斑棒摄像头的旋转
                    // 注意：第一步和第二部顺序不能调换
                    var rotateBitmap = BitmapUtil.rotateBitmap(bitmap, -90f)
                    // 2 将图片数据缩放至640*480大小
                    var scaledBitmap = rotateBitmap.scale(640, 480)
                    // 3 将 Bitmap 转换为 RGBA 字节数组
                    var imageData = BitmapUtil.bitmapToRGBABytes(scaledBitmap);
                    // 4 调用NCNN模型进行图片推理
                    yolov12.processImage(imageData, mSurface)
                    // 5 回收bitmap
                    bitmap.recycle()
                    rotateBitmap.recycle()
                    scaledBitmap.recycle()
                    // 6 更新状态
                    onUIProcessListener.updateReceivedDataStatus("帧 $frameSeq 已显示", true)
                    // 7 移除已处理的帧
                    for (i in 0 until frameSeq) {
                        if (frames.containsKey(i)) {
                            frames.remove(i)
                        }
                    }
                } else {
                    Log.e(TAG, "无法从数据创建图像，数据长度: ${imageData.size}")
                    onUIProcessListener.updateReceivedDataStatus("帧 $frameSeq 解码失败", true)
                }
                // 8 清理资源
                outputStream.close()
            }
        } catch (e: Exception) {
            Log.e(TAG, "处理帧失败: ${e.message}", e)
            onUIProcessListener.updateReceivedDataStatus("处理帧 $frameSeq 失败: ${e.message}", true)
        }
    }

    private fun resetFrameState(frameSeq: Int, pkgCount: Int) {
        currentFrameSeq = frameSeq
        currentFramePkgCount = pkgCount
        receivedPacketCount = 0
        Log.d(TAG, "开始新的帧: $frameSeq, 预期包数: $pkgCount")
    }

    fun openWifiManager(context: Context) {
        WifiHelper.instance.openWifiManager(context)
    }

    fun releaseWifiManager() {
        WifiHelper.instance.releaseWifiManager()
    }

}